#proevolytx@gmail.com
#2012/9/15

from lexer0 import *
from parser0 import *

test = Lexer("{ int x; char y; { bool y; x; y; } x; y; }",
             ["int", "char", "bool"],
             ["{", "}", ";"])

class Env:
    def __init__(s, p):
        s.p = p
        s.t = {}
    def add(s, symid, syminfo):
        if symid in s.t:
            raise Exception("duplicated declaration")
        else:
            s.t[symid] = syminfo
    def get(s, symid):
        if symid in s.t:
            return s.t[symid]
        if s.p != None:
            return s.p.get(symid)

class EnvParser(Parser):
    def program(s):
        s.top = None
        s.stmts()
    
    def block(s):
        s.top = Env(s.top)
        
        s.match(("op", "{"))
        s.out += "{";
        
        s.decls()
        s.stmts()
        
        s.match(("op", "}"))
        s.out += "}"
        s.top = s.top.p
    
    def decls(s):
        while s.la in [("int",), ("bool",), ("char",)]:
            s.decl()
    
    def decl(s):
        if s.la in [("int",), ("bool",), ("char",)]:
            symtype = s.la[0]
            s.nextlex()
            symid = s.la[1]
            s.top.add(symid, symtype)
            s.match(("token",))
            s.match(("op", ";"))
        else:
            raise Exception("type expected, " + str(s.la) + " instead")
    
    def stmts(s):
        while s.la != None and (s.la[0] == "token" or s.la == ("op", "{")):
            s.stmt()
    
    def stmt(s):
        if s.la == ("op", "{"):
            s.block()
        else:
            s.factor()
            s.match(("op", ";"))

    def factor(s):
        if s.la != None and s.la[0] == "token":
            s.out += s.la[1] + ":" + s.top.get(s.la[1]) + "; "
            s.nextlex()
        else:
            raise Exception("token expected, " + str(s.la) + " instead")

lex = test.ScanAll()
print lex
p = EnvParser(lex)
p.program()
print p.out
